package com.aizuda.boot.modules.business.negotiation.controller;

import com.aizuda.boot.modules.business.contract.dto.SingleResponse;
import com.aizuda.boot.modules.business.contract.dto.UserInfo;
import com.aizuda.boot.modules.business.contract.util.AuthUtil;
import com.aizuda.boot.modules.common.constant.enums.ResponseCodeEnum;
import com.aizuda.boot.modules.business.filling.domain.request.PageQuery;
import com.aizuda.boot.modules.business.negotiation.entity.dto.CreateNegotiationReqDTO;
import com.aizuda.boot.modules.business.negotiation.entity.dto.NegotiationConfigSaveDTO;
import com.aizuda.boot.modules.business.negotiation.entity.dto.NegotiationConfigUpdateDTO;
import com.aizuda.boot.modules.business.negotiation.entity.dto.NegotiationListReqDTO;
import com.aizuda.boot.modules.business.negotiation.entity.dto.ContractVersionHistoryRespDTO;
import com.aizuda.boot.modules.business.negotiation.entity.dto.InviteNegotiationReqDTO;
import com.aizuda.boot.modules.business.negotiation.entity.dto.ExitNegotiationReqDTO;
import com.aizuda.boot.modules.business.negotiation.entity.dto.CancelNegotiationReqDTO;
import com.aizuda.boot.modules.business.negotiation.entity.dto.NegotiationAnnouncementRespDTO;
import com.aizuda.boot.modules.business.negotiation.entity.dto.NegotiationResumeReqDTO;
import com.aizuda.boot.modules.business.negotiation.entity.dto.NegotiationAnnouncementListRespDTO;
import com.aizuda.boot.modules.business.negotiation.entity.dto.NegotiationAnnouncementListReqDTO;
import com.aizuda.boot.modules.business.negotiation.entity.dto.NegotiationAnnouncementUpdateReqDTO;
import com.aizuda.boot.modules.business.negotiation.entity.dto.NegotiationAnnouncementDeleteReqDTO;
import com.aizuda.boot.modules.business.negotiation.entity.dto.NegotiationAnnouncementCreateReqDTO;
import com.aizuda.boot.modules.business.negotiation.entity.dto.NegotiationInstanceAnnouncementUpdateReqDTO;
import com.aizuda.boot.modules.business.negotiation.entity.vo.CreateNegotiationRespDTO;
import com.aizuda.boot.modules.business.negotiation.entity.vo.NegotiationConfigShowDTO;
import com.aizuda.boot.modules.business.negotiation.entity.vo.NegotiationListRespDTO;
import com.aizuda.boot.modules.business.negotiation.entity.vo.NegotiationShowListDTO;
import com.aizuda.boot.modules.business.negotiation.entity.ContractNegotiationInstanceEntity;
import com.aizuda.boot.modules.business.negotiation.entity.ContractNegotiationNodeInstanceEntity;
import com.aizuda.boot.modules.business.negotiation.service.ContractNegotiationConfigService;
import com.aizuda.boot.modules.business.negotiation.service.ContractNegotiationService;
import com.aizuda.boot.modules.business.contract_operation_log.service.ContractOperationLogService;
import com.aizuda.boot.modules.business.contract_operation_log.domain.entity.ContractOperationLog;
import com.aizuda.boot.modules.common.constant.enums.WorkFlowTypeEnums;
import com.aizuda.boot.modules.common.constant.enums.ActionTypeEnums;
import com.aizuda.boot.modules.common.constant.enums.SourceTypeEnums;
import com.aizuda.boot.modules.flw.flow.FlowTaskAccessStrategy;
import com.aizuda.service.web.UserSession;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.aizuda.boot.modules.flw.entity.dto.NextNodesDTO;
import com.aizuda.boot.modules.flw.entity.dto.ProcessInfoDTO;
import com.aizuda.boot.modules.flw.entity.vo.TaskApprovalVO;
import com.aizuda.boot.modules.flw.service.IFlwProcessTaskService;
import com.aizuda.boot.modules.flw.service.IFlwProcessFormService;
import com.aizuda.boot.modules.flw.entity.FlwProcessForm;
import com.aizuda.bpm.engine.entity.FlwTask;
import com.aizuda.bpm.engine.FlowLongEngine;
import com.aizuda.bpm.engine.entity.FlwTaskActor;
import com.aizuda.bpm.engine.entity.FlwInstance;
import com.aizuda.bpm.engine.entity.FlwHisInstance;
import com.aizuda.boot.modules.common.MessageEvent;
import com.aizuda.boot.modules.system.entity.enums.BusinessType;
import com.aizuda.boot.modules.system.entity.SysUser;
import com.aizuda.boot.modules.system.service.ISysUserService;
import com.aizuda.boot.modules.business.contract.entity.ContractEntity;
import com.aizuda.boot.modules.business.contract.service.ContractService;
import com.aizuda.boot.modules.business.contract.entity.ContractFieldValueEntity;
import com.aizuda.boot.modules.business.contract.mapper.ContractFieldValueMapper;
import com.aizuda.boot.modules.common.constant.enums.SystemFieldsEnum;
import org.springframework.context.ApplicationEventPublisher;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import com.aizuda.common.toolkit.JacksonUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.List;
import java.util.ArrayList;
import java.util.Date;


/**
 * 合同协商控制器
 */
@Slf4j
@RestController
@RequestMapping("/contract/negotiation")
@Tag(name = "合同协商接口")
public class ContractNegotiationController {
    
    @Resource
    private ContractNegotiationService contractNegotiationService;

    @Resource
    private ContractNegotiationConfigService contractNegotiationConfigService;

    @Resource
    private IFlwProcessTaskService flwProcessTaskService;
    
    @Resource
    private IFlwProcessFormService flwProcessFormService;

    @Resource
    private FlowLongEngine flowLongEngine;
    
    @Resource
    private ContractOperationLogService contractOperationLogService;

    @Resource
    private ApplicationEventPublisher applicationEventPublisher;

    @Resource
    private ISysUserService sysUserService;

    @Resource
    private ContractService contractService;

    @Resource
    private ContractFieldValueMapper contractFieldValueMapper;

    /**
     * 根据系统字段代码获取字段ID
     */
    private Long getFieldIdByCode(String code) {
        try {
            return contractService.getFieldIdByCode(code);
        } catch (Exception e) {
            log.warn("Failed to get field ID by code: {}", code, e);
            return null;
        }
    }

    /**
     * 查询协商列表
     * @param dto 查询条件
     * @return 协商列表分页数据
     */
    @Operation(summary = "查询协商列表")
    @PostMapping("/list")
    public SingleResponse<Page<NegotiationListRespDTO>> getNegotiationList(@RequestBody NegotiationListReqDTO dto) {
        log.debug("协商列表查询接口被调用");
        Page<NegotiationListRespDTO> result = contractNegotiationService.getNegotiationList(dto);
        log.debug("协商列表查询完成 - 总记录数: {}, 当前页记录数: {}", 
                result.getTotal(), result.getRecords().size());
        return SingleResponse.of(result);
    }
    
    //todo 目前只是手动添加配置，后续需要根据合同类型自动添加配置
    /**
     * 创建新的协商实例
     * @param dto 创建协商请求参数
     * @return 创建结果
     */
    @Operation(summary = "创建新的协商实例")
    @PostMapping("/create")
    public SingleResponse<CreateNegotiationRespDTO> createNegotiation(@RequestBody @Validated CreateNegotiationReqDTO dto) {
        CreateNegotiationRespDTO result = contractNegotiationService.createNegotiation(dto);
        return SingleResponse.of(result);
    }

    @Operation(summary = "查询协商配置列表")
    @PostMapping("/showList")
    public SingleResponse<IPage<NegotiationShowListDTO>> getNegotiationShowList(@RequestBody PageQuery query) {
        return contractNegotiationConfigService.getNegotiationShowList(query);
    }

    /**
     * 根据合同ID查询协商实例信息
     * @param contractId 合同ID
     * @return 协商实例信息（包含流程实例ID、当前任务ID、下一个节点assigneeMap、processForm等）
     */
    @Operation(summary = "根据合同ID查询协商实例信息")
    @GetMapping("/instance/{contractId}")
    public SingleResponse<Map<String, Object>> getNegotiationInstance(@PathVariable Integer contractId) {
        Map<String, Object> result = new HashMap<>();
        
        // 查询协商实例（包含所有状态，不只是进行中的）
        ContractNegotiationInstanceEntity instance = contractNegotiationService.getNegotiationByContractIdAllStatus(contractId);
        if (instance != null) {
            result.put("negotiationInstanceId", instance.getId());
            result.put("processInstanceId", instance.getProcessInstanceId());
            result.put("negotiationStatus", instance.getNegotiationStatus());
            result.put("negotiationStage", instance.getNegotiationStage());
            result.put("announcementText", instance.getAnnouncementText()); // 添加协商公告文本

            // 获取当前用户信息
            UserSession userSession = UserSession.getLoginInfo();
            boolean shouldIncludeTaskInfo = false;
            
            if (userSession != null && userSession.getId() != null) {
                // 检查当前用户是否在审批列表中
                shouldIncludeTaskInfo = checkCurrentUserApprovalPermission(userSession.getId(), instance);
            }
            
            // 查询当前任务
            ContractNegotiationNodeInstanceEntity currentTask = contractNegotiationService.getCurrentTask(instance.getId());
            if (currentTask != null) {
                result.put("currentNodeId", currentTask.getId());
                result.put("currentNodeStatus", currentTask.getStatus());
                
                // 只有轮到当前用户审批时才返回任务相关信息
                if (shouldIncludeTaskInfo) {
                    result.put("currentTaskId", currentTask.getTaskId());
                    
                    // 如果有任务信息快照，也返回
                    if (StringUtils.hasText(currentTask.getRuleConfigSnapshot())) {
                        try {
                            Map<String, Object> taskInfo = JacksonUtils.readMap(currentTask.getRuleConfigSnapshot());
                            result.put("taskInfo", taskInfo);
                        } catch (Exception e) {
                            log.error("解析任务信息失败", e);
                        }
                    }
                } else {
                    log.info("用户 {} 不在当前任务审批列表中，不返回task相关信息，合同ID: {}", userSession.getId(), contractId);
                }
            }
            
            // 获取下一个节点的assigneeMap和相关信息
            if (instance.getProcessInstanceId() != null) {
                try {
                    // 检查流程是否已经结束
                    FlwInstance currentInstance = flowLongEngine.queryService().getInstance(instance.getProcessInstanceId());
                    FlwHisInstance historyInstance = flowLongEngine.queryService().getHistInstance(instance.getProcessInstanceId());
                    boolean isProcessActive = currentInstance != null;
                    result.put("isProcessActive", isProcessActive);
                    
                    // 添加流程实例状态 - 从历史实例获取，因为FlwInstance没有instanceState字段
                    if (historyInstance != null) {
                        result.put("instanceState", historyInstance.getInstanceState());
                    }
                    
                    // 用于传递给approvalInfo的taskId
                    Long taskIdForApprovalInfo = null;
                    
                    if (isProcessActive) {
                        // 流程还在进行中，获取下一个节点信息
                        // 创建NextNodesDTO
                        NextNodesDTO nextNodesDTO = new NextNodesDTO();
                        nextNodesDTO.setInstanceId(instance.getProcessInstanceId());
                        
                        // 获取下一个节点的assigneeMap
                        Map<String, Object> nextNodesInfo = flwProcessTaskService.listNextNodesAssigneeMap(nextNodesDTO);
                        if (nextNodesInfo != null) {
                            result.put("nextNodeType", nextNodesInfo.get("nodeType"));
                            result.put("assigneeMap", nextNodesInfo.get("assigneeMap"));
                            result.put("nextNodeCount", nextNodesInfo.get("nodeCount"));
                        }
                        
                        // 获取下一个需要执行的taskId（如果有活跃任务）
                        List<FlwTask> activeTasks = flowLongEngine.queryService().getTasksByInstanceId(instance.getProcessInstanceId());
                        if (activeTasks != null && !activeTasks.isEmpty()) {
                            // 保存taskId用于调用approvalInfo，无论当前用户是否有审批权限
                            taskIdForApprovalInfo = activeTasks.get(0).getId();
                            
                            // 只有轮到当前用户审批时才返回任务ID相关信息到result中
                            if (shouldIncludeTaskInfo) {
                                // 返回第一个活跃任务的ID作为下一个需要执行的taskId
                                result.put("taskId", activeTasks.get(0).getId());
                                result.put("nextTaskKey", activeTasks.get(0).getTaskKey());
                                result.put("nextTaskName", activeTasks.get(0).getTaskName());
                                
                                // 如果有多个任务，返回所有任务信息
                                if (activeTasks.size() > 1) {
                                    List<Map<String, Object>> allTasks = new ArrayList<>();
                                    for (FlwTask task : activeTasks) {
                                        Map<String, Object> taskMap = new HashMap<>();
                                        taskMap.put("taskId", task.getId());
                                        taskMap.put("taskKey", task.getTaskKey());
                                        taskMap.put("taskName", task.getTaskName());
                                        allTasks.add(taskMap);
                                    }
                                    result.put("allActiveTasks", allTasks);
                                }
                            }
                        }
                    } else {
                        // 流程已经结束，从历史记录中获取信息
                        if (historyInstance != null) {
                            result.put("processEndTime", historyInstance.getEndTime());
                            result.put("processStatus", "COMPLETED");
                        }
                        
                        // 对于已结束的流程，不再查询活跃任务，但仍返回基本信息
                        result.put("processStatus", "COMPLETED");
                        result.put("message", "协商流程已结束");
                    }
                    
                    // 获取processForm（无论流程是否结束都可以获取）
                    FlwProcessForm processForm = flwProcessFormService.getByInstanceId(instance.getProcessInstanceId());
                    if (processForm != null) {
                        result.put("processForm", processForm.getContent());
                    }
                    
                    // 调用审批信息接口获取processApprovals和modelContent
                    try {
                        ProcessInfoDTO processInfoDTO = new ProcessInfoDTO();
                        processInfoDTO.setInstanceId(instance.getProcessInstanceId());
                        // 如果有活跃任务，传递taskId；否则为null让approvalInfo方法自动处理
                        if (taskIdForApprovalInfo != null) {
                            processInfoDTO.setTaskId(taskIdForApprovalInfo);
                        }
                        
                        TaskApprovalVO approvalInfo = flwProcessTaskService.approvalInfo(processInfoDTO);
                        if (approvalInfo != null) {
                            result.put("processApprovals", approvalInfo.getProcessApprovals());
                            result.put("modelContent", approvalInfo.getModelContent());
                        }
                    } catch (Exception e) {
                        log.error("获取审批信息失败 - 流程实例ID: {}", instance.getProcessInstanceId(), e);
                    }
                    
                } catch (Exception e) {
                    log.error("获取流程信息失败 - 流程实例ID: {}", instance.getProcessInstanceId(), e);
                    result.put("error", e.getMessage());
                }
            }
        }
        
        return SingleResponse.of(result);
    }
    
    /**
     * 检查当前用户是否在当前任务的审批列表中
     * @param userId 用户ID
     * @param instance 协商实例
     * @return 是否在审批列表中
     */
    private boolean checkCurrentUserApprovalPermission(Long userId, ContractNegotiationInstanceEntity instance) {
        try {
            if (instance.getProcessInstanceId() == null) {
                return false;
            }
            
            // 获取当前活跃的任务
            List<FlwTask> activeTasks = flowLongEngine.queryService().getTasksByInstanceId(instance.getProcessInstanceId());
            if (activeTasks == null || activeTasks.isEmpty()) {
                return false;
            }
            
            // 检查用户是否有权限操作任何一个活跃任务
            for (FlwTask task : activeTasks) {
                // 获取任务的参与者
                var taskActorsOpt = flowLongEngine.queryService().getActiveTaskActorsByTaskId(task.getId());
                if (taskActorsOpt.isPresent()) {
                    List<FlwTaskActor> taskActors = taskActorsOpt.get();
                    
                    // 使用FlowTaskAccessStrategy检查用户权限
                    FlowTaskAccessStrategy accessStrategy = new FlowTaskAccessStrategy();
                    FlwTaskActor allowedActor = accessStrategy.isAllowed(userId.toString(), taskActors);
                    
                    if (allowedActor != null) {
                        log.info("用户 {} 有权限操作任务 {}", userId, task.getId());
                        return true;
                    }
                }
            }
            
            log.info("用户 {} 没有权限操作当前流程的任务", userId);
            return false;
            
        } catch (Exception e) {
            log.error("检查审批权限失败 - 用户ID: {}, 流程实例ID: {}", userId, instance.getProcessInstanceId(), e);
            return false;
        }
    }

    /**
     * 根据合同ID查询协商完整信息
     * @param contractId 合同ID
     * @return 协商实例完整信息（包含所有节点、参与者、统计信息等）
     */
    @Operation(summary = "根据合同ID查询协商完整信息")
    @GetMapping("/fullInfo/{contractId}")
    public SingleResponse<Map<String, Object>> getNegotiationFullInfo(@PathVariable Integer contractId) {
        Map<String, Object> fullInfo = contractNegotiationService.getNegotiationFullInfo(contractId);
        
        try {
            // 获取当前用户ID
            UserSession userSession = UserSession.getLoginInfo();
            if (userSession != null && userSession.getId() != null) {
                // 先检查用户是否已经查看过
                boolean hasViewed = contractNegotiationService.hasUserViewedNegotiation(contractId, userSession.getId());
                
                if (!hasViewed) {
                    // 未查看过，记录查看合同的操作日志
                    logViewContract(contractId, userSession.getId());
                    
                    // 更新参与者的查看状态
                    contractNegotiationService.updateParticipantViewStatus(contractId, userSession.getId());
                } else {
                    log.info("用户已查看过该协商信息，跳过日志记录和状态更新，合同ID: {}, 用户ID: {}", contractId, userSession.getId());
                }
            }
        } catch (Exception e) {
            log.error("处理查看合同协商信息的后续操作失败", e);
            // 日志记录和状态更新失败不影响主业务
        }
        
        return SingleResponse.of(fullInfo);
    }
    
    /**
     * 记录查看合同的操作日志
     * @param contractId 合同ID
     * @param userId 用户ID
     */
    private void logViewContract(Integer contractId, Long userId) {
        try {
            // 构建日志数据
            ContractOperationLog operationLog = ContractOperationLog.builder()
                    .contractId(contractId.longValue())
                    .flowType(WorkFlowTypeEnums.NEGOTIATION_WORKFLOW.getCode())
                    .actionType(ActionTypeEnums.VIEW_CONTRACT.getCode())
                    .sourceType(SourceTypeEnums.USER.getCode())
                    .userId(userId)
                    .actionTime(new Date())
                    .build();
            
            // 保存日志
            contractOperationLogService.save(operationLog);
            log.info("记录查看合同协商信息日志成功，合同ID: {}, 用户ID: {}", contractId, userId);
            
        } catch (Exception e) {
            log.error("记录查看合同协商信息日志失败，合同ID: {}, 用户ID: {}", contractId, userId, e);
        }
    }

    @Operation(summary = "创建协商列配置表")
    @PostMapping("/save")
    public SingleResponse saveNegotiationConfig(@RequestBody NegotiationConfigSaveDTO negotiationConfigSaveDTO){
        return contractNegotiationConfigService.saveNegotiationConfig(negotiationConfigSaveDTO);
    }

    @Operation(summary = "更新协商配置")
    @PutMapping("/update")
    public SingleResponse updateNegotiationConfig(@RequestBody NegotiationConfigUpdateDTO negotiationConfigUpdateDTO){
        return contractNegotiationConfigService.updateNegotiationConfig(negotiationConfigUpdateDTO);
    }

    @Operation(summary = "删除协商配置")
    @DeleteMapping("/delete/{id}")
    public SingleResponse deleteNegotiationConfig(@PathVariable Long id){
        return contractNegotiationConfigService.deleteNegotiationConfig(id);
    }

    @Operation(summary = "删除协商实例")
    @PostMapping("/delete/instance/{contractId}")
    public SingleResponse<Boolean> deleteNegotiation(@PathVariable Integer contractId) {
        try {
            boolean result = contractNegotiationService.deleteNegotiationByContractId(contractId);
            if (result) {
                return SingleResponse.of(true);
            } else {
                return SingleResponse.failure(ResponseCodeEnum.SHOW_MSG.getCode(), "未找到合同的协商实例或删除失败");
            }
        } catch (Exception e) {
            log.error("删除协商失败，合同ID: {}", contractId, e);
            return SingleResponse.failure(ResponseCodeEnum.SHOW_MSG.getCode(), "删除协商失败：" + e.getMessage());
        }
    }

    @Operation(summary = "邀请用户参与协商")
    @PostMapping("/invite")
    public SingleResponse<Boolean> inviteNegotiation(@RequestBody @Validated InviteNegotiationReqDTO dto) {
        try {
            boolean result = contractNegotiationService.inviteNegotiation(dto);
            if (result) {
                // 邀请成功后发送飞书通知
                sendInviteNotification(dto);
                return SingleResponse.of(true);
            } else {
                return SingleResponse.failure(ResponseCodeEnum.SHOW_MSG.getCode(), "邀请协商失败，可能未找到可邀请的协商实例、用户已是参与者或您无权限邀请");
            }
        } catch (Exception e) {
            log.error("邀请协商失败，合同ID: {}, 用户ID: {}", dto.getContractId(), dto.getInvitedUserId(), e);
            return SingleResponse.failure(ResponseCodeEnum.SHOW_MSG.getCode(), "邀请协商失败：" + e.getMessage());
        }
    }

    @Operation(summary = "根据合同ID激活协商")
    @PostMapping("/resume")
    public SingleResponse<Boolean> resumeNegotiation(@RequestBody @Validated NegotiationResumeReqDTO dto) {
        try {
            boolean result = contractNegotiationService.resumeNegotiationByContractId(dto.getContractId(), dto.getAnnouncementText());
            if (result) {
                return SingleResponse.of(true);
            } else {
                return SingleResponse.failure(ResponseCodeEnum.SHOW_MSG.getCode(), "激活协商失败，可能未找到待激活的协商实例");
            }
        } catch (Exception e) {
            log.error("激活协商失败，合同ID: {}, 协商公告: {}", dto.getContractId(), dto.getAnnouncementText(), e);
            return SingleResponse.failure(ResponseCodeEnum.SHOW_MSG.getCode(), "激活协商失败：" + e.getMessage());
        }
    }


    @Operation(summary = "获取协商配置")
    @GetMapping("/get/{id}")
    public SingleResponse<NegotiationConfigShowDTO> getNegotiationConfig(@PathVariable Long id){
        return contractNegotiationConfigService.getNegotiationConfig(id);
    }

    @Operation(summary = "退出协商")
    @PostMapping("/exit")
    public SingleResponse<Boolean> exitNegotiation(@RequestBody @Validated ExitNegotiationReqDTO dto) {
        Long userId = null;
        try {
            // 获取当前登录用户
            UserSession userSession = UserSession.getLoginInfo();
            if (userSession == null || userSession.getId() == null) {
                return SingleResponse.failure(ResponseCodeEnum.SHOW_MSG.getCode(), "用户未登录");
            }
            userId = userSession.getId();

            boolean result = contractNegotiationService.exitNegotiation(dto.getContractId(), userId);
            if (result) {
                return SingleResponse.of(true);
            } else {
                return SingleResponse.failure(ResponseCodeEnum.SHOW_MSG.getCode(), "退出协商失败，可能您不是协商参与者或您是某个节点的唯一审批人");
            }
        } catch (Exception e) {
            log.error("退出协商失败，合同ID: {}, 用户ID: {}", dto.getContractId(), userId, e);
            return SingleResponse.failure(ResponseCodeEnum.SHOW_MSG.getCode(), "退出协商失败：" + e.getMessage());
        }
    }

    @Operation(summary = "修改协商状态")
    @PutMapping("/status/{id}")
    public SingleResponse updateStatus(@PathVariable Long id){
        return contractNegotiationConfigService.updateStatus(id);
    }
    
    /**
     * 获取合同版本历史列表
     * @param contractId 合同ID
     * @return 版本历史列表
     */
    @Operation(summary = "获取合同版本历史列表")
    @GetMapping("/version-history/{contractId}")
    public SingleResponse<List<ContractVersionHistoryRespDTO>> getContractVersionHistory(@PathVariable Integer contractId) {
        List<ContractVersionHistoryRespDTO> result = contractNegotiationService.getContractVersionHistory(contractId);
        return SingleResponse.of(result);
    }

    @Operation(summary = "取消协商")
    @PostMapping("/cancel")
    public SingleResponse<Boolean> cancelNegotiation(@RequestBody @Validated CancelNegotiationReqDTO dto) {
        try {
            boolean result = contractNegotiationService.cancelNegotiation(dto.getContractId());
            if (result) {
                return SingleResponse.of(true);
            } else {
                return SingleResponse.failure(ResponseCodeEnum.SHOW_MSG.getCode(), "取消协商失败，可能协商不存在或状态不允许取消");
            }
        } catch (Exception e) {
            log.error("取消协商失败，合同ID: {}", dto.getContractId(), e);
            return SingleResponse.failure(ResponseCodeEnum.SHOW_MSG.getCode(), "取消协商失败：" + e.getMessage());
        }
    }

    @Operation(summary = "获取协商公告配置")
    @GetMapping("/announcement")
    public SingleResponse<NegotiationAnnouncementRespDTO> getNegotiationAnnouncement() {
        try {
            NegotiationAnnouncementRespDTO result = contractNegotiationService.getNegotiationAnnouncement();
            return SingleResponse.of(result);
        } catch (Exception e) {
            log.error("获取协商公告配置失败", e);
            return SingleResponse.failure(ResponseCodeEnum.SHOW_MSG.getCode(), "获取协商公告配置失败：" + e.getMessage());
        }
    }

    @Operation(summary = "获取协商公告配置列表")
    @PostMapping("/announcement/list")
    public SingleResponse<IPage<NegotiationAnnouncementListRespDTO>> getNegotiationAnnouncementList(@RequestBody @Validated NegotiationAnnouncementListReqDTO dto) {
        try {
            IPage<NegotiationAnnouncementListRespDTO> result = contractNegotiationService.getNegotiationAnnouncementList(dto);
            return SingleResponse.of(result);
        } catch (Exception e) {
            log.error("获取协商公告配置列表失败", e);
            return SingleResponse.failure(ResponseCodeEnum.SHOW_MSG.getCode(), "获取协商公告配置列表失败：" + e.getMessage());
        }
    }

    @Operation(summary = "更新协商公告配置")
    @PutMapping("/announcement/update")
    public SingleResponse updateNegotiationAnnouncement(@RequestBody @Validated NegotiationAnnouncementUpdateReqDTO dto) {
        try {
            boolean result = contractNegotiationService.updateNegotiationAnnouncement(dto);
            if (result) {
                return SingleResponse.of(true);
            } else {
                return SingleResponse.failure(ResponseCodeEnum.SHOW_MSG.getCode(), "更新协商公告配置失败");
            }
        } catch (Exception e) {
            log.error("更新协商公告配置失败", e);
            return SingleResponse.failure(ResponseCodeEnum.SHOW_MSG.getCode(), "更新协商公告配置失败：" + e.getMessage());
        }
    }

    @Operation(summary = "删除协商公告配置")
    @PostMapping("/announcement/delete")
    public SingleResponse deleteNegotiationAnnouncement(@RequestBody @Validated NegotiationAnnouncementDeleteReqDTO dto) {
        try {
            boolean result = contractNegotiationService.deleteNegotiationAnnouncement(dto);
            if (result) {
                return SingleResponse.of(true);
            } else {
                return SingleResponse.failure(ResponseCodeEnum.SHOW_MSG.getCode(), "删除协商公告配置失败");
            }
        } catch (Exception e) {
            log.error("删除协商公告配置失败", e);
            return SingleResponse.failure(ResponseCodeEnum.SHOW_MSG.getCode(), "删除协商公告配置失败：" + e.getMessage());
        }
    }

    @Operation(summary = "创建协商公告配置")
    @PostMapping("/announcement/create")
    public SingleResponse<Boolean> createNegotiationAnnouncement(@RequestBody @Validated NegotiationAnnouncementCreateReqDTO dto) {
        try {
            boolean result = contractNegotiationService.createNegotiationAnnouncement(dto);
            if (result) {
                return SingleResponse.of(true);
            } else {
                return SingleResponse.failure(ResponseCodeEnum.SHOW_MSG.getCode(), "创建协商公告配置失败");
            }
        } catch (Exception e) {
            log.error("创建协商公告配置失败", e);
            return SingleResponse.failure(ResponseCodeEnum.SHOW_MSG.getCode(), "创建协商公告配置失败：" + e.getMessage());
        }
    }

    @Operation(summary = "修改协商实例公告")
    @PostMapping("/instance/announcement/update")
    public SingleResponse updateNegotiationInstanceAnnouncement(@RequestBody @Validated NegotiationInstanceAnnouncementUpdateReqDTO dto) {
        try {
            boolean result = contractNegotiationService.updateNegotiationInstanceAnnouncement(dto);
            if (result) {
                return SingleResponse.of(true);
            } else {
                return SingleResponse.failure(ResponseCodeEnum.SHOW_MSG.getCode(), "修改协商实例公告失败");
            }
        } catch (Exception e) {
            log.error("修改协商实例公告失败", e);
            return SingleResponse.failure(ResponseCodeEnum.SHOW_MSG.getCode(), "修改协商实例公告失败：" + e.getMessage());
        }
    }

    /**
     * 发送邀请协商通知
     */
    private void sendInviteNotification(InviteNegotiationReqDTO dto) {
        try {
            // 获取当前用户（邀请人）信息
            UserInfo currentUser = AuthUtil.getCurrentUser();
            if (currentUser == null) {
                log.warn("无法获取当前用户信息，跳过发送邀请通知");
                return;
            }

            // 获取被邀请用户信息
            SysUser invitedUser = sysUserService.getById(dto.getInvitedUserId());
            if (invitedUser == null) {
                log.warn("被邀请用户不存在，用户ID: {}", dto.getInvitedUserId());
                return;
            }

            // 获取合同信息
            ContractEntity contract = contractService.getById(dto.getContractId());
            if (contract == null) {
                log.warn("合同不存在，合同ID: {}", dto.getContractId());
                return;
            }

            // 获取合同名称
            String contractName = getContractName(dto.getContractId());

            // 构建通知内容
            String title = "审核邀请通知";
            String content = String.format("您被邀请参与合同【%s】的审核，邀请人：%s，请及时查看并参与审核。",
                    contractName != null ? contractName : "未知合同",
                    currentUser.getNickName() != null ? currentUser.getNickName() : currentUser.getUsername());

            // 发送消息事件
            MessageEvent messageEvent = new MessageEvent();
            messageEvent.setTitle(title);
            messageEvent.setContent(content);
            messageEvent.setCreateId(currentUser.getId());
            messageEvent.setCreateBy(currentUser.getNickName() != null ? currentUser.getNickName() : currentUser.getUsername());
            messageEvent.setCategory(2); // 2表示待办消息
            messageEvent.setBusinessId(dto.getContractId().longValue());
            messageEvent.setBusinessType(BusinessType.negotiation.name()); // 使用协商业务类型
            messageEvent.setUserIds(List.of(dto.getInvitedUserId()));

            // 发布事件，触发飞书通知
            applicationEventPublisher.publishEvent(messageEvent);

            log.info("已发送协商邀请通知，合同ID: {}, 被邀请用户ID: {}, 邀请人: {}",
                    dto.getContractId(), dto.getInvitedUserId(), currentUser.getNickName());

        } catch (Exception e) {
            log.error("发送协商邀请通知失败，合同ID: {}, 被邀请用户ID: {}",
                    dto.getContractId(), dto.getInvitedUserId(), e);
        }
    }

    /**
     * 获取合同名称
     */
    private String getContractName(Integer contractId) {
        try {
            // 根据合同名称字段ID查询合同名称
            Long contractNameFieldId = getFieldIdByCode(SystemFieldsEnum.CONTRACT_NAME.getCode());
            if (contractNameFieldId == null) {
                log.warn("未找到合同名称字段配置，合同ID: {}", contractId);
                return null; // 如果找不到字段配置，返回null
            }

            List<ContractFieldValueEntity> fieldValues = contractFieldValueMapper.selectByContractId(contractId);
            for (ContractFieldValueEntity fieldValue : fieldValues) {
                if (contractNameFieldId.equals(fieldValue.getFieldId())) {
                    return fieldValue.getFieldValue();
                }
            }
            return null;
        } catch (Exception e) {
            log.error("获取合同名称失败，合同ID: {}", contractId, e);
            return null;
        }
    }
}